package com.quick.develop.flowable.schedule;

import cn.hutool.core.collection.CollUtil;
import com.quick.develop.flowable.constant.BpmConstants;
import com.quick.develop.flowable.enums.BpmExecuteCmd;
import com.quick.develop.framework.utils.DateUtils;
import com.quick.develop.flowable.framework.cmd.SetHistoricTaskDescCmd;
import com.quick.develop.flowable.framework.factory.FlowServiceFactory;
import com.quick.develop.flowable.schedule.core.BpmScheduleHandler;
import com.quick.develop.flowable.service.task.IBpmCommentService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableOptimisticLockingException;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;

import static com.quick.develop.flowable.enums.BpmErrorCodeConstants.AUTO_COMPLETE_READ_ERROR;
import static com.quick.develop.framework.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;

/**
 * desc:
 *
 * @author junyuan.liu
 * @date 2023/7/17 13:53
 */
@Slf4j
@Component
public class BpmAutoCompleteReadTask extends FlowServiceFactory implements BpmScheduleHandler {
    @Resource
    private IBpmCommentService bpmCommentService;
    

    @Value("${flowable.custom.auto-read.keys:#{null}}")
    private Set<String> autoReadKeys;

    @Value("${flowable.custom.auto-read.before:#{null}}")
    @DateTimeFormat(pattern = YYYY_MM_DD_HH_MM_SS)
    private Date before;

    @Value("${flowable.custom.auto-read.after:#{null}}")
    @DateTimeFormat(pattern = YYYY_MM_DD_HH_MM_SS)
    private Date after;

    private static final String[] SET_VALUES = new String[] {
            "PTD_distribute_RY", "distribute_process_ry", "HCNPC_Receiving_letters_ry",
            "HSNPE-distribute_process_ry_file", "HSNPC-distribute_process_ry_file", "HSNPC-distribute_process_ry_file_01",
            "HSNPE-distribute_process_ry_file_01", "HSNPC_distribute_ry_upgrade", "HSNPE_distribute_ry_upgrade",
            "HSNPC_distribute_ry_description", "HSNPE_distribute_ry_description", "HSNPE_personnel_distribution", 
            "HSNPC_personnel_distribution", "HSNPE_personnel_distribution_record", "HSNPC_personnel_distribution_record",
            "HSNPE_personnel_distribution_upgrade", "HSNPC_personnel_distribution_upgrade","HSNPC-distribute_process_ry",
            "HSNPE-distribute_process_ry", "receive_distribute_process_ry", "HSNPE-receive_distribute_process_ry",
            "PTD_distribute_RY", "t_PTD_distribute_RY", "PTD_revoke_distribute_RY",
            "HCNPC_PTD_distribute_RY", "HCNPC_revoke_distribute_RY", "EMM_distribute_ry",
            "IMM_distribute_ry", "HSNPE-EMM_distribute_ry", "HSNPE-IMM_distribute_ry"
    };

    private static final Set<String> DEFAULT_KEYS = new HashSet<>(Arrays.asList(SET_VALUES));

    private Set<String> autoCompleteReadKeys;
    
    @Override
    @Async
    public void execute() {
        LocalDate localDate = LocalDate.now();
        if (Objects.isNull(before)) {
            before = DateUtils.toDate(localDate.plusMonths(-3)) ;
        }
        if (Objects.isNull(after)) {
            after = DateUtils.toDate(localDate.plusMonths(-5)) ;
        }
        autoCompleteReadKeys  = new HashSet<>();
        if (CollUtil.isEmpty(autoReadKeys)) {
            autoCompleteReadKeys = DEFAULT_KEYS;
        } else {
            autoCompleteReadKeys.addAll(autoReadKeys);
            autoCompleteReadKeys.addAll(DEFAULT_KEYS);
        }
        List<Task> list = getReadTask();
        for (Task task : list) {
            try {
                complete(task, 0);
            } catch (Exception e) {
                log.error(AUTO_COMPLETE_READ_ERROR.getMsg(), task.getId(), e.getMessage(), e);
                e.printStackTrace();
            }
        }

    }
    
    private List<Task> getReadTask() {
        return taskService.createTaskQuery()
                .processDefinitionKeyIn(autoCompleteReadKeys)
                .taskCreatedAfter(after)
                .taskCreatedBefore(before)
                .orderByTaskCreateTime().asc()
                .list();
    }
    
    private void complete(Task task, int count) {
        if (count > 2) {
            return;
        }
        String taskId = task.getId();
        try {
            if (DelegationState.PENDING.equals(task.getDelegationState())) {
                taskService.resolveTask(taskId, null);
            }
            bpmCommentService.addComment(taskId, task.getProcessInstanceId(), BpmExecuteCmd.READ.getMsg(), BpmExecuteCmd.READ, null);
            // 标记一下
            managementService.executeCommand(new SetHistoricTaskDescCmd(taskId, BpmConstants.AUTO_READ));
            taskService.complete(taskId, null);
        } catch (FlowableOptimisticLockingException e) {
            count = count + 1; 
            complete(task, count);
        }

    }
    
    
    
}
